﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SlimDX.Direct3D9;
using System.Drawing;
using SlimDX;
using System.Runtime.InteropServices;

namespace SlimWater
{
    struct ScreenVertex
    {
        public Vector4 Position;
        public Vector2 TexCoord0;

        public ScreenVertex(Vector4 Position, Vector2 TexCoord0)
        {
            this.Position = Position;
            this.TexCoord0 = TexCoord0;
        }
    }

    class ScreenQuad
    {
        Device device;

        Surface surface;
        RenderToSurface rts;
        
        public Texture texture;

        VertexDeclaration vertexDecl;
        Effect effect;
        VertexBuffer vb;

        public ScreenQuad(Device device, int windowWidth, int windowHeight)
        {
            this.device = device;

            texture = new Texture(device, windowWidth, windowHeight, 1, Usage.RenderTarget, Format.A8R8G8B8, Pool.Default);
            texture.DebugName = "Screen Texture";

            surface = texture.GetSurfaceLevel(0);
            surface.DebugName = "Screen Surface";

            rts = new RenderToSurface(device, windowWidth, windowHeight, Format.A8R8G8B8, Format.D16);

            effect = Effect.FromFile(device, "../../data/screen.fx", ShaderFlags.None);

            effect.Technique = "Simple";

            // the four quad's vertices:
            vb = new VertexBuffer(device, 4 * Marshal.SizeOf(typeof(ScreenVertex)),
                Usage.WriteOnly, VertexFormat.None, Pool.Managed);
            vb.DebugName = "Screen VertexBuffer";

            var stream = vb.Lock(0, 0, LockFlags.None);
            stream.WriteRange(new[] {
				new ScreenVertex(new Vector4(0, 0, 1, 1), new Vector2(0, 0)),
                new ScreenVertex(new Vector4(0, windowHeight, 1, 1), new Vector2(0, 1)),
                new ScreenVertex(new Vector4(windowWidth, 0, 1, 1), new Vector2(1, 0)),
                new ScreenVertex(new Vector4(windowWidth, windowHeight, 1, 1), new Vector2(1, 1)),
			});
            vb.Unlock();

            vertexDecl = new VertexDeclaration(device, new[] {
				new VertexElement(0, 0, DeclarationType.Float4, DeclarationMethod.Default, DeclarationUsage.PositionTransformed, 0), 
                new VertexElement(0, 16, DeclarationType.Float2, DeclarationMethod.Default, DeclarationUsage.TextureCoordinate, 0), 
				VertexElement.VertexDeclarationEnd
        	});
        }

        public void BeginScene()
        {
            rts.BeginScene(surface, device.Viewport);
        }

        public void EndScene()
        {
            rts.EndScene(Filter.Linear);
        }

        public void Render(Vector3 cameraEP, double time)
        {
            effect.Technique = (cameraEP.Y < 0) ? "Underwater" : "Simple";
                
            effect.SetValue("xTime", (float) time);

            effect.Begin(0);
            for (int i = 0; i < effect.GetTechniqueDescription(effect.Technique).Passes; ++i)
            {
                effect.BeginPass(i);
                device.SetStreamSource(0, vb, 0, Marshal.SizeOf(typeof(ScreenVertex)));
                device.SetTexture(0, texture);
                device.VertexDeclaration = vertexDecl;
                device.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
                effect.EndPass();
            }
            effect.End();
        }
    }
}
